/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.matching;

import java.util.regex.Pattern;

import org.w3c.dom.Document;

import cgl.narada.event.NBEvent;
import cgl.narada.event.TemplateProfileAndSynopsisTypes;
import cgl.narada.matching.regex.ClientRegExMatching;
import cgl.narada.matching.regex.RegExProfile;
import cgl.narada.matching.tagvaluepairs.TagValueClientMatching;
import cgl.narada.matching.xmlxpath.ClientXPathMatching;

/** Facilitates the matching of events across multiple profile types 

    @author Shrideep Pallickara
    $Date$
    $Revision$
*/

public class CrossMatching {
  private ClientXPathMatching xpathMatching;
  private ClientRegExMatching regexMatching;
  private TagValueClientMatching tagValueMatching;
  private String moduleName = "CrossMatching: ";
  
  public CrossMatching() {
    xpathMatching = new ClientXPathMatching(0,3, null);
    regexMatching = new ClientRegExMatching(0,3, null);
    tagValueMatching = new TagValueClientMatching(0,3, null);
  }

  public boolean 
  checkIfEventMatchesConstraints(NBEvent nbEvent, Profile[] profiles) {
    int numOfProfiles = profiles.length;

    for (int i=0; i< numOfProfiles; i++) {
      Profile _profile = profiles[i];
      if (checkIfEventMatchesConstraint(nbEvent, _profile)) {
	return true;
      }
    }
    
    return false;
  }

  public boolean 
  checkIfEventMatchesConstraint(NBEvent nbEvent, Profile profile) {
    boolean match=false;
    
    Object contentSynopsis = nbEvent.getContentSynopsis();
    int eventType = nbEvent.getContentSynopsisType();
    int profileType = profile.getProfileType();
    
    if (profileType == TemplateProfileAndSynopsisTypes.STRING) {
      match = matchStringConstraint(nbEvent, profile);
    }
    
    if (profileType == TemplateProfileAndSynopsisTypes.INTEGER) {
       match = matchIntegerConstraint(nbEvent, profile);
    }
    
    if (profileType == TemplateProfileAndSynopsisTypes.XML) {
      match = matchXPathConstraint(nbEvent, profile);
    }
    
    if (profileType == TemplateProfileAndSynopsisTypes.REGULAR_EXPRESSIONS) {
      match = matchRegExConstraint(nbEvent, profile);
    }
    
    if (profileType == TemplateProfileAndSynopsisTypes.TAG_VALUE_PAIRS) {
      match = matchTagValueConstraint(nbEvent, profile);
    }
    
    return match;
  }

  

  private boolean matchStringConstraint(NBEvent nbEvent, Profile profile) {
    String contentSynopsis = nbEvent.getContentSynopsis().toString();
    String subscription = (String) profile.getSubscription();
    
    if (contentSynopsis != subscription) {
      return false;
    }
    
    return true;
  }
  
  
  private boolean matchIntegerConstraint(NBEvent nbEvent, Profile profile) {
    String contentSynopsis = nbEvent.getContentSynopsis().toString();
    
    try {
      Integer intObject = new Integer(Integer.parseInt(contentSynopsis) );
      Integer subscription = (Integer) profile.getSubscription();
      
      if (intObject != subscription) {
	return false;
      }
    } catch (NumberFormatException nfe) {
      return false;
    }
    
    return true;    
  }


  private boolean matchXPathConstraint(NBEvent nbEvent, Profile profile) {
    if (nbEvent.getContentSynopsisType() != 
	TemplateProfileAndSynopsisTypes.XML) {
      return false;
    }
    
    Document document = (Document) nbEvent.getContentSynopsis();
    String xpathQuery = (String) profile.getSubscription();
    
    return xpathMatching.documentMatchesXPathQuery(document, xpathQuery);
  }


  private boolean matchRegExConstraint(NBEvent nbEvent, Profile profile) {
    String contentSynopsis = nbEvent.getContentSynopsis().toString();

    RegExProfile regExProfile = (RegExProfile) profile;
    Pattern regExPattern = regExProfile.getPattern();

    return regexMatching.evaluateRegExOnInput(regExPattern, contentSynopsis);
  }
  

  private boolean matchTagValueConstraint(NBEvent nbEvent, Profile profile) {
    if (nbEvent.getContentSynopsisType() != 
	TemplateProfileAndSynopsisTypes.TAG_VALUE_PAIRS) {
      return false;
    }
    
    tagValueMatching.addSubscriptionProfile(profile);
    Object dests = tagValueMatching.matchEvent(nbEvent);
    tagValueMatching.removeSubscriptionProfile(profile);
    
    if (dests == null) {
      return false;
    }

    return true;
  }

}
